www.gusucode.com > VANET Toolbox- A Vehicular Network Simulator based on DES 程序工具箱matlab源码 > VANET Toolbox- A Vehicular Network Simulator based on DES/VANET_Toolbox/VANET_Toolbox_2018a/macFrame.m

    classdef macFrame < handle
    %macFrame Mac frame
    %   Object to represent all the files in a mac frame.
    
    properties (Constant)
        % the protocol version is zero based on the standard 802.11-2012
        protocolVersionField = [0 0];
        MANAGEMENTTYPE = uint8(0);
        CONTROLTYPE = uint8(1);
        DATATYPE = uint8(2);
        ACKSUBTYPE =  uint8(13) % binary 1101
        CTSSUBTYPE = uint8(12) % binary 1100
        
        % QOS subtypes used for QoS field
        QOSDATA  = uint8(8) %binary 1000
        QOSDATAACK = uint8(9) %binary 1001
        QOSDATAPOLL = uint8(10) %binary 1010
        QOSDATAACKPOLL = uint8(11) % binary 1011
        QOSNULL = uint8(12) % binary 1100
        
        %ACK policies
        % Normal Ack or Implicit Block Ack Request '00'
        NORMALACK = uint8(0) ; % '00'
        NOACK = uint8(2) ; %'10'
        %No Explicit Acknowledgement or Scheduled Ack under PSMP
        NOEXACK = uint8(1); %'01'
        %Block Acknowledgement
        BLKACK = uint8(3); % '11'
        
    end
    properties
        %Fields inside the Frame Control field
        
        typeField;
        subtypeField;
        toDSField;
        fromDSField;
        moreFragField;
        retryField;
        pwrMgtField;
        moreDataField;
        protectedFrameField;
        orderFrameField;
        
        % the Duration ID can be used for Duration or ID Field
        % based on the value
        durantionIDField
        
        % Address 1 contains the receive address (RA) and is present in all
        % frames. Address 2 contains the transmit address (TA) and is present in all frames except
        % ACK and CTS.
        address1Field;
        address2Field;
        % Address 3 is present in data and management frames. In a data frame, the address
        % carried by the Address 3 field is dependent on the To DS and From DS bit settings
        
        address3Field;
        address4Field;
        
        fragmentNumberField;
        sequenceNumberField;
        
        %        The Traffic Identifier (TID) subfield identifies the TC or TS to which the corresponding
        %           MSDU or MSDU fragment in the frame body belongs. The TID subfield also
        %           identifies the TC or TS for which a TXOP is being requested through the setting of the
        %            TXOP Duration Requested or Queue Size subfields.
        TIDField
        ESOPField
        ACKPolicy
        AMSDUPresent
        APPSbufferState
        TXOPlimit
        TXOPduration
        queueSize
        isAP
        %data need to enconde already in array of bits
%         data = [];
        data=zeros(1,1);
        fcsGen
        fcsDet                                
    end
    properties (Dependent)
        %Frame Control field is dependet of many subparameters
        frameControlField
        %The Sequence Control field consists of a 4-bit Fragment Number
        %and a 12-bit Sequence Number
        sequenceControlField % Sequence Control field
        frameArray
        idField
        durantionField
        QOScontrolField;
        
    end
    
    % Mthods for attibutes
    
    methods
        function obj = macFrame()
            
            %create default values for the fields
            %considering it is a ACK package
            
            % Management type
            obj.typeField = obj.CONTROLTYPE;
            % Subtype ACK 1101
            obj.subtypeField = obj.ACKSUBTYPE;
            % to and from DS are 0 for management frame
            obj.toDSField = 0;
            obj.fromDSField = 0;
            %It is set to 0 in MPDUs that contain a complete MSDU
            obj.moreFragField = 0;
            %The Retry field is set to 1 in any data or management frame that is a retransmission of an
            %earlier frame. It is set to 0 in all other frames. A receiving station uses this indication to aid
            %in eliminating duplicate frames.
            obj.retryField = 0 ;
            %A value of 0 indicates that the station will be in active
            %mode, while a value of 1 indicates that the station will be in Power Save (PS) mode. This
            %field is always set to 0 by the AP.
            obj.pwrMgtField = 0 ;
            
            obj.moreDataField = 0;
            %The Protected Frame field, when set to 1, indicates that the Frame Body field has been
            %encrypted.
            obj.protectedFrameField = 0;
            %As may be appreciated, this field was never widely used. It is reused in 802.11n to
            %indicate the presence of HT Control field in QoS Data frames. Prior to 802.11n, this bit
            %was reserved in QoS Data frames, which always had it set to 0.
            obj.orderFrameField = 0;
            
            obj.durantionIDField =  49153;
            obj.address1Field = 0 ;
            obj.address2Field = 0;
            
            obj.address3Field = 0 ;
            obj.address4Field = 0 ;
            
            obj.fragmentNumberField = 0 ;
            obj.sequenceNumberField = 0 ;
            
            % QOS is optional, it just to create the variables
            obj.TIDField = 0;
            obj.ESOPField = 0;
            obj.ACKPolicy = 0;
            obj.AMSDUPresent = 0;
            obj.APPSbufferState = 0;
            obj.TXOPlimit = 0;
            obj.TXOPduration = 0;
            obj.queueSize = 0;
            obj.isAP = 0;
            %create the CRC generator and decoder
            
            obj.fcsGen = comm.CRCGenerator('z^32 + z^26 + z^23 + z^22 + z^16 + z^12 + z^11 + z^10 + z^8 + z^7 + z^5 + z^4 + z^2 + z + 1');
            obj.fcsDet = comm.CRCDetector('z^32 + z^26 + z^23 + z^22 + z^16 + z^12 + z^11 + z^10 + z^8 + z^7 + z^5 + z^4 + z^2 + z + 1');
            
            
        end
        function value = get.idField(obj)
            %             If the two high order bits are set in a PS-Poll frame then the low
            %               order 14 bits are interpreted as the association identifier (AID).
            %               Binary 1100000000000000 Decimal 49152
            if obj.durantionIDField >= 49152
                value = obj.durantionIDField - 49152;
            else
                value = 0 ;
            end
            
            
        end
        function value = get.durantionField(obj)
            %           When the value of the Duration/ID field is less than 32 768 (high order bit not set), then
            %           the value is interpreted as a duration in microseconds and used to update the network
            %           allocation vector (NAV).
            if obj.durantionIDField < 32768
                value =   obj.durantionIDField;
            else
                value = 0 ;
            end
            
            
        end
        function value = get.frameControlField(obj)
            %             value = strcat(obj.protocolVersionField,obj.typeField,obj.subtypeField,...
            %                 obj.toDSField,obj.fromDSField,obj.moreFragField,obj.retryField,...
            %                 obj.pwrMgtField,obj.moreDataField,obj.protectedFrameField,obj.orderFrameField);
            value = obj.protocolVersionField ;
            value = [ value de2bi(obj.typeField,2,'left-msb')];
            value = [ value de2bi(obj.subtypeField,4,'left-msb')];
            value = [ value de2bi(obj.toDSField,1,'left-msb')];
            value = [ value de2bi(obj.fromDSField,1,'left-msb')];
            value = [ value de2bi(obj.moreFragField,1,'left-msb')];
            value = [ value de2bi(obj.retryField,1,'left-msb')];
            value = [ value de2bi(obj.pwrMgtField,1,'left-msb')];
            value = [ value de2bi(obj.moreDataField,1,'left-msb')];
            value = [ value de2bi(obj.protectedFrameField,1,'left-msb')];
            value = [ value de2bi(obj.orderFrameField,1,'left-msb')];
            
            
        end
        function status = decodeframeControlField(obj,inputarray)
            %             value = strcat(obj.protocolVersionField,obj.typeField,obj.subtypeField,...
            %                 obj.toDSField,obj.fromDSField,obj.moreFragField,obj.retryField,...
            %                 obj.pwrMgtField,obj.moreDataField,obj.protectedFrameField,obj.orderFrameField);
            % decode the frame control field
            % the array nust be a 16 positon array
            if numel(inputarray) ~= 16
                status = 0 ;
                return ;
            end
            % the protocol version is read only 
            obj.typeField = bi2de(inputarray(3:4),'left-msb');
            obj.subtypeField = bi2de(inputarray(5:8),'left-msb');
            obj.toDSField = bi2de(inputarray(9),'left-msb');
            obj.fromDSField = bi2de(inputarray(10),'left-msb');
            obj.moreFragField = bi2de(inputarray(11),'left-msb');
            obj.retryField = bi2de(inputarray(12),'left-msb');
            obj.pwrMgtField = bi2de(inputarray(13),'left-msb');
            obj.moreDataField = bi2de(inputarray(14),'left-msb');
            obj.protectedFrameField = bi2de(inputarray(15),'left-msb');
            obj.orderFrameField = bi2de(inputarray(16),'left-msb');
            status = 1;
            return
            
            
        end
        function value = get.QOScontrolField(obj)
            tempb0b3 = 0;
            tempb4 = 0;
            tempb5b6 = 0;
            tempb7 = 0;
            tempb8b15 = 0;
            
            if obj.typeField == obj.DATATYPE
                if obj.isAP
                    if obj.subtypeField == obj.QOSDATAPOLL
                        tempb0b3 = obj.TIDField;
                        tempb4 = obj.ESOPField;
                        tempb5b6 = double(obj.ACKPolicy);
                        tempb7 = obj.AMSDUPresent;
                        tempb8b15 = obj.TXOPlimit;
                    elseif obj.subtypeField == obj.QOSDATA || obj.subtypeField == obj.QOSDATAACK || obj.subtypeField == obj.QOSNULL
                        tempb4 = obj.ESOPField;
                        tempb8b15 = obj.APPSbufferState;
                    end
                elseif obj.subtypeField == obj.QOSDATA
                    % dependes of the value of bit 4 if Zero use the TXOP Duration Requested
                    % if bit 4 is not zero, use Queue Size
                    tempb8b15 = obj.TXOPduration;
                end
                
                value = [ de2bi(tempb0b3,4,'left-msb')];
                value = [ value de2bi(tempb4,1,'left-msb')];
                value = [ value de2bi(tempb5b6,2,'left-msb')];
                value = [ value de2bi(tempb7,1,'left-msb')];
                value = [ value de2bi(tempb8b15,8,'left-msb')];                                                
            else
                value=0;
            end
        end
        function status = decodeQOScontrolField(obj,inputarray)
            if numel(inputarray) ~= 16
                status = 0 ;
                return ;
            else
                status = 1;
            end
            if obj.typeField == obj.DATATYPE
                if obj.isAP
                    if obj.subtypeField == obj.QOSDATAPOLL
                        obj.TIDField = bi2de(inputarray(1:4),'left-msb');
                        obj.ESOPField = bi2de(inputarray(5),'left-msb');
                        obj.ACKPolicy = bi2de(inputarray(6:7),'left-msb');
                        obj.AMSDUPresent = bi2de(inputarray(8),'left-msb');
                        obj.TXOPlimit = bi2de(inputarray(9:16),'left-msb');
                    elseif obj.subtypeField == obj.QOSDATA || obj.subtypeField == obj.QOSDATAACK || obj.subtypeField == obj.QOSNULL
                        obj.ESOPField = bi2de(inputarray(5),'left-msb');
                        obj.APPSbufferState = bi2de(inputarray(9:16),'left-msb');
                    end
                elseif obj.subtypeField == obj.QOSDATA
                    % dependes of the value of bit 4 if Zero use the TXOP Duration Requested
                    % if bit 4 is not zero, use Queue Size
                    obj.TXOPduration= bi2de(inputarray(9:16),'left-msb');
                end
            end
        end
        function value = get.sequenceControlField(obj)
            
            
            value = [ de2bi(obj.fragmentNumberField,4,'left-msb') de2bi(obj.sequenceNumberField,12,'left-msb')];
            
            
        end
        function status = decodeSequenceControlField(obj,inputarray)
            
            if numel(inputarray) ~= 16
                status = 0 ;
                return ;
            end
            obj.fragmentNumberField = bi2de(inputarray(1:4),'left-msb');
            obj.sequenceNumberField = bi2de(inputarray(5:16),'left-msb');
            status = 1;
            
            
        end
        function set.data(obj,value)
            
            if iscolumn(value)
                newvalue = value.';                
                nbits = numel(newvalue);                
                rest = rem(nbits,8);
                if(rest > 0)
                   finalvalue = [newvalue zeros(1,(8-rest))]; 
                   obj.data=finalvalue;
                else
                    obj.data=double(newvalue);
                end    
            else                
                nbits = numel(value);    
                rest=rem(nbits,8);
                if(rest > 0)
                   final1value = [value zeros(1,(8-rest))]; 
                   obj.data=final1value;
                else
                    obj.data=double(value);
                end    
            end                
            obj.data=reshape(obj.data,[1,numel(obj.data)]);                        
            
        end
        function set.typeField(obj,value)
            if isnumeric(value)
                obj.typeField = uint8(value);
            elseif ischar(value)
                lowerValue = lower(value);
                switch lowerValue
                    
                    case {'00','management'}
                        obj.typeField = obj.MANAGEMENTTYPE;
                    case {'01', 'control'}
                        obj.typeField = obj.CONTROLTYPE;
                    case {'10', 'data'}
                        obj.typeField = obj.DATATYPE;
                end
            else
                msg = 'Wrong format of type field';
                error(msg);
            end
            
        end
        function set.subtypeField(obj,value)
            if isnumeric(value)
                obj.subtypeField = uint8(value);
            else
                msg = 'Wrong format of subtype field';
                error(msg);
            end
            
        end
        function set.ACKPolicy(obj,value)
            if isnumeric(value)
                obj.ACKPolicy = uint8(value);
            elseif ischar(value)
                
                lowerValue = lower(value);
                switch lowerValue
                    
                    case {'00','normal'}
                        obj.ACKPolicy = obj.NORMALACK;
                    case {'10', 'no'}
                        obj.ACKPolicy = obj.NOACK;
                    case {'01', 'noex'}
                        obj.ACKPolicy = obj.NOEXACK;
                    case {'11', 'block'}
                        obj.ACKPolicy = obj.BLKACK;
                end
            else
                msg = 'Wrong format of ack policy';
                error(msg);
            end
            
        end
        function value = get.frameArray(obj)
            % for data we combine the data and header in a n*1 binary array
            % the ack is only a header.
            value = [ obj.frameControlField de2bi(obj.durantionIDField,16,'left-msb')];
            value = [ value  de2bi(obj.address1Field,48,'left-msb')];
            if  (obj.typeField ~= obj.CONTROLTYPE)  || (obj.subtypeField ~= obj.ACKSUBTYPE && obj.subtypeField ~= obj.CTSSUBTYPE)
                value = [ value  de2bi(obj.address2Field,48,'left-msb')];
            else
                
            end
            if  (obj.typeField == obj.MANAGEMENTTYPE || obj.typeField == obj.DATATYPE)
                value = [ value  de2bi(obj.address3Field,48,'left-msb')];
            end
            value = [ value  obj.sequenceControlField];
            if (obj.toDSField == 1 && obj.fromDSField == 1)
                value = [ value  de2bi(obj.address4Field,48,'left-msb')];
            end
            if( obj.typeField == obj.DATATYPE && obj.subtypeField >= obj.QOSDATA && obj.subtypeField <= obj.QOSNULL)
                value = [ value  obj.QOScontrolField];
            end
            
            
            % There is a extra optional filed HT Control that will not
            % be implement because 802.11p dont use it.            
            if ~isempty(obj.data)
%                 datareshape=reshape(obj.data,[1,numel(obj.data)]);                
                tempData=zeros(1,numel(obj.data));
                for i=1:numel(obj.data)
                    tempData(1,i)=obj.data(i);
                end
%                 value = [ value  obj.data];
                value=[value tempData];
            end
            
            
            %conversion of the value to run over the CRC 32 lib without
            %problem
            valueTransLogical =  logical(value.');
            value = step(obj.fcsGen,valueTransLogical);
        end
        
        function [status , msg] = decodeArray(obj,inputarray)
            status = 0;
            currentindex = 1;
            obj.fcsGen.reset();
            obj.fcsDet.reset();
            [ lin, col ] = size(inputarray);
            if lin>col
                rxArray=zeros(lin,col);
                rxArray=inputarray;
            else %col>lin                
                rxArray=zeros(col,lin);
                rxArray=inputarray.';
            end
            
%             if (col > lin)                
%                 inputarray = inputarray.';
%             end
                
%             [verfArray, errors] = step(obj.fcsDet,inputarray);
            [verfArray, errors] = step(obj.fcsDet,rxArray);
            verfArray = verfArray.';
            sizeInput = numel(verfArray);
            if errors == 0
                % The crc verify correcty
                status = obj.decodeframeControlField(verfArray(currentindex:currentindex+15));
                if status
                    currentindex = currentindex+16;
                    obj.durantionIDField =  bi2de(verfArray(currentindex:currentindex+15),'left-msb');
                    currentindex = currentindex+16;
                    obj.address1Field =  bi2de(verfArray(currentindex:currentindex+47),'left-msb');
                    currentindex = currentindex + 48;
                    if  (obj.typeField ~= obj.CONTROLTYPE)  || (obj.subtypeField ~= obj.ACKSUBTYPE && obj.subtypeField ~= obj.CTSSUBTYPE)
                        obj.address2Field = bi2de(verfArray(currentindex:currentindex+47),'left-msb');
                        currentindex = currentindex + 48;
                    end
                    if  (obj.typeField == obj.MANAGEMENTTYPE || obj.typeField == obj.DATATYPE)
                        obj.address3Field = bi2de(verfArray(currentindex:currentindex+47),'left-msb');
                        currentindex = currentindex + 48;
                    end
                    status = obj.decodeSequenceControlField(verfArray(currentindex:currentindex+15));
                    currentindex = currentindex+16;
                    if status
                        if (obj.toDSField == 1 && obj.fromDSField == 1)
                            obj.address4Field = bi2de(verfArray(currentindex:currentindex+47),'left-msb');
                            currentindex = currentindex + 48;
                        end
                        if( obj.typeField == obj.DATATYPE)
                            
                            if(obj.subtypeField >= obj.QOSDATA && obj.subtypeField <= obj.QOSNULL)
                                status = obj.decodeQOScontrolField((verfArray(currentindex:currentindex+15)));
                                currentindex = currentindex+16;
                                if ~status
                                    status = 0;
                                    msg = 'error QOS field';
                                    return;
                                end
                            end
                            
                            
                            if (sizeInput >  currentindex)
                                obj.data = verfArray(currentindex:end);
                            end
                             
                        end
                        msg = 'success';
                    else
                        status = 0;
%                          msg = 'error decoding Sequence Control';
                        msg='errSqCo';
                        return;
                    end
                else
%                     msg = 'error decoding Frame Control Field';
                    msg='errConF';
                    status = 0;
                    return;
                end
            else
                  msg = 'CRC Err';
                    status = 0;
                    return;
            end
        end
    end
    
    
end